#include "stdafx.h"
#include "PacketQueue.h"

extern "C"
{

#include "libavcodec\avcodec.h"
//#include "libavformat\avformat.h"
//#include "libavutil\error.h"
//#include "libavutil\imgutils.h"
//#include "libswscale\swscale.h"
//#include "libswresample/swresample.h"
//
#include "sdl.h"
}

inline int getNextIndex(const int& nCurIndex, const int& nMaxIndex)
{
	return (nCurIndex + 1) % nMaxIndex;
}

CPacketQueue::CPacketQueue(const int& nMaxSize /*= 100*/)
	: m_nMaxSize(nMaxSize)
	, m_nSize(0)
	, m_nFrontIndex(0)
	, m_nBackIndex(0)
	, m_pPacketAry(nullptr)
	, m_pAryMutex(nullptr)
{
	m_pPacketAry = new AVPacket*[nMaxSize];
	memset(m_pPacketAry, 0, sizeof(m_pPacketAry[0])*nMaxSize);
	m_pAryMutex = SDL_CreateMutex();
}


CPacketQueue::~CPacketQueue()
{
	if (m_pPacketAry)
	{
		//also need delete the element pointer
		delete[] m_pPacketAry;
		m_pPacketAry = nullptr;
	}
	if (m_pAryMutex)
	{
		SDL_DestroyMutex(m_pAryMutex);
	}
}

AVPacket * CPacketQueue::front()
{
	if (auto pPacket = m_pPacketAry[m_nFrontIndex])
	{
		//m_nFrontIndex = getNextIndex(m_nFrontIndex, m_nMaxSize);
		return pPacket;
	}
	return nullptr;
}

AVPacket * CPacketQueue::popFront()
{
	SDL_LockMutex(m_pAryMutex);
	if (auto pPacket = m_pPacketAry[m_nFrontIndex])
	{
		m_pPacketAry[m_nFrontIndex] = nullptr;
		m_nFrontIndex = getNextIndex(m_nFrontIndex, m_nMaxSize);
		m_nSize--;
		SDL_UnlockMutex(m_pAryMutex);
		return pPacket;
	}
	SDL_UnlockMutex(m_pAryMutex);
	return nullptr;
}

bool CPacketQueue::push(AVPacket * pPacket)
{
	assert(pPacket);
	if (m_pPacketAry[m_nBackIndex])
		return false;
	else
	{
		SDL_LockMutex(m_pAryMutex);
		m_pPacketAry[m_nBackIndex] = pPacket;
		m_nBackIndex = getNextIndex(m_nBackIndex, m_nMaxSize);
		m_nSize++;
		SDL_UnlockMutex(m_pAryMutex);
		return true;
	}
}

inline int CPacketQueue::getSize()
{
	return m_nSize;
	SDL_LockMutex(m_pAryMutex);
	auto n = m_nBackIndex - m_nFrontIndex;
	SDL_UnlockMutex(m_pAryMutex);
	if (n >= 0)
		return n;
	else
		return m_nMaxSize + n;
}

bool CPacketQueue::isFull()
{
	return getSize() == m_nMaxSize;
}

bool CPacketQueue::isEmpty()
{
	return getSize() == 0;
}
